/*->c.script */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>
#include <locale.h>
#include <stdarg.h>


#include "h.os"
#include "h.wimp"
#include "h.sprite"
#include "h.werr"
#include "h.wimpt"
#include "h.bbc"
#include "h.akbd"



#include "h.DrawLevel0"


#include "h.wos"

#include "h.ram"
#include "h.trans"

#include "h.def"
#include "h.main"
#include "h.file"
#include "h.term"
#include "h.timex"

#include "h.xext"

#include "h.vtdef"
#include "h.vtfile"
#include "h.vtchar"
#include "h.vtscr"
#include "h.vtlo"
#include "h.vtwimp"
#include "h.vtcol"
#include "h.vtprint"
#include "h.vtsend"
#include "h.vtkey"

#include "h.pr"
#include "h.tek"
#include "h.tekint"

#include "h.vxdef"
#include "h.vxkey"
#include "h.vxsend"
#include "h.vxwimp"
#include "h.vxbuff"
#include "h.vxprint"

#include "h.ftp"
#include "h.batch"
#include "h.xmodem"
#include "h.zmextra"



#include "ckcdeb.h"                     /* Debug & other symbols */
#include "ckcker.h"                     /* Kermit symbols */
#include "ckcfil.h"                     /* File-related symbols */

#include "h.ckcdef"



#include "h.view"

#include "h.vax"


#include "h.mym"
#include "h.serial"  
#include "h.serialdev"

#include "h.dir"
#include "h.key"

#include "h.script"





/*****************************************************************************/

int logfile;


void writetolog(char * format, ...)
{
 va_list args;
 char string[256];
 char temp[128];
 char * p;
 FILE * fp;

 strcpy(temp,format);
 trans(temp,sizeof(temp));

 writesystimedate(string);
 p=string+strlen(string);
 strcpy(p," : ");
 p+=3;

 va_start(args, format);
 vsprintf(p, temp, args);
 va_end(args);

 if(logfile)
 {
  fp=fopen(path(LOGP),"a");
  if(fp)
  {
   fwrite(string,strlen(string),1,fp);
   fputc('\n',fp);
   fclose(fp);
  }
 }
}


/*****************************************************************************/

static int  modemdriverloaded;
static char drivername[12];
static int  pendingdriver;
static char pendname[12];

static int  tonedial;


void specifydriver(int fp)
{
 char * p=stringptr(stack[fp]);
 int    len=strlen(p);

 if(len && len<12)
 {
  strcpy(pendname,p);
  pendingdriver=1;
 }
}



int activatedriver(void)
{
 int  tx=txbitrate;
 int  rx=rxbitrate;
 int  d=databits;
 int  p=paritybits;
 int  s=stopbits;
 int  ans=answer;
 int  fl=flow;
 int  result;

 result=1;

 if(modemdriverloaded)
 {

  xexec("modem_initiate",NULL,&deviceport,&result);

  if(!result)
  {
   active=1;

   settxrate(tx);

   setrxrate(rx);
   setanswer(ans);
   setdatabits(d);

   setparitybits(p);
   setstopbits(s);
   setflow(fl);

   tonedial=drivertonedial(tonedial);

   onlinechange();
  }
 }

 return(result);
}



void deactivatedriver(void)
{
 if(active && modemdriverloaded)
 {
  xexec("modem_terminate",NULL,NULL,NULL);
 }
}



void changedriver(int wasactive)
{
 char string[128];

 if(pendingdriver && zlevel==0)
 {
  if(modemdriverloaded)
  {
   deactivate();
   xremfile();
   modemdriverloaded=0;
  }

  sprintf(string,"%s.%s",path(DRVP),pendname);
  if(xaddfile(string,0,1))
  {
   modemdriverloaded=1;
   strcpy(drivername,pendname);
   if(wasactive) activate();
  }
  pendingdriver=0;
 }
}



/*****************************************************************************/

char * unquotec(char * input,char * output)
{
 char * r;
 char * w;

 r=input;
 w=output;

 while(*r)
 {
  if(*r=='\"' || *r=='\\') *w++='\\';
  *w++=*r++;
 }

 *w=0;

 return(output);
}



static int setvar(int index,int * var)
{
 int val=stack[index];
 int change;

 if(val==0 || val>0)
 {
  val=val!=0;
  change=(*var!=val);
  *var=val;
 }
 else change=0;

 return(change);
}


void setdefterm(int fp)
{
 int term=stack[fp];
 if(term>=0 && term<TERMMAX)  defaultterminal=term;
}


void setchoices(int fp)
{
 int temp;

 setvar(fp+0,&newdata);
 setvar(fp+1,&doconfirm);
 setvar(fp+2,&logfile);
 
 temp=stack[fp+3];
 if(temp>=0 && temp<4) printsettype((3+temp)%4);

 setvar(fp+4,&tonedial);
}



void setxterm(int fp)
{
 setterm(stack[fp]);
}


void setftp(int fp)
{
 int ftp=stack[fp];
 if(ftp>=0 && ftp<PNONE) ftprotocol=ftp;
}  


void setxmodem(int fp)
{
 fp=stack[fp];
 if(fp==1 || fp==2) xmode=fp;
}


void setymodem(int fp)
{
 int mode=stack[fp];
 int size=stack[fp+1];

 if(mode>=1 && mode<=3) ymode=mode;

 if(size==128)  ysize=0;
 else
 if(size==1024) ysize=1;
}


void setzmodem(int fp)
{
 setvar(fp,&Wantfcs32);
 setvar(fp+1,&AutoResume);
 setvar(fp+2,&zmautodload);
}


void setcet(int fp)
{
 setvar(fp,&vxslotel);
 setvar(fp+1,&vxcetel);
 strcpy(vxceteol,stringptr(stack[fp+2]));
 setvar(fp+3,&vxautoresume);
}



void setkermit(int fp)
{
 setvar(fp+0,&binary);
 setvar(fp+1,&swcapr);
 setvar(fp+2,&ebqflg);
 ebq=codechar(stringptr(stack[fp+3]));
 bctr=stack[fp+4];                     /* setvar(fp+4,&bctr); */
}



void ksettxp(int fp)
{
 spsiz=stack[fp+1];
 npad=stack[fp+2];

 padch=codechar(stringptr(stack[fp+3]));
 mystch=codechar(stringptr(stack[fp+4]));
 seol=codechar(stringptr(stack[fp+5]));

 timint=stack[fp+6];

 myctlq=codechar(stringptr(stack[fp+7]));
}



void ksetrxp(int fp)
{
 urpsiz=stack[fp+1];
 mypadn=stack[fp+2];

 mypadc=codechar(stringptr(stack[fp+3]));
 stchr=codechar(stringptr(stack[fp+4]));
 eol=codechar(stringptr(stack[fp+5]));

 rtimo=stack[fp+6];

 ctlq=codechar(stringptr(stack[fp+7]));
}



void setkermitparam(int fp)
{
 if(stack[fp]==0) ksettxp(fp);
 else
 if(stack[fp]==1) ksetrxp(fp);
}



void setasciitx(int fp)
{
 int temp;

 txprompt=codechar(stringptr(stack[fp+0]));

 temp=stack[fp+1];
 if(temp==10) txeol=ASCIILF;
 else
 if(temp==13) txeol=ASCIICR;
 else
 if(temp==14) txeol=ASCIICRLF;
 else
 if(temp==15) txeol=ASCIILFCR;
 else
 if(temp==16) txeol=ASCIIRAW;

 txbegin=codechar(stringptr(stack[fp+2]));
 txend=codechar(stringptr(stack[fp+3]));
 txstart=codechar(stringptr(stack[fp+4]));
 txstop=codechar(stringptr(stack[fp+5]));

 txcharpace=stack[fp+6];
 txlinepace=stack[fp+7]*10;

 setvar(fp+8,&txexpand);
 setvar(fp+9,&asctxe);
}



void setasciirx(int fp)
{
 int temp;

 rxprompt=codechar(stringptr(stack[fp+0]));

 temp=stack[fp+1];
 if(temp==10) rxeol=ASCIILF;
 else
 if(temp==13) rxeol=ASCIICR;

 rxtprompt=codechar(stringptr(stack[fp+2]));
 rxpace=stack[fp+3]*10;
 rxbegin=codechar(stringptr(stack[fp+4]));
 rxend=codechar(stringptr(stack[fp+5]));
 setvar(fp+6,&ascrxe);
}


int scriptpoll=1;

void setpoll(int fp)
{
 scriptpoll=stack[fp];
}


void setbatch(int fp)
{
 int xdisplay=stack[fp];
 int xsort=stack[fp+1];
 if(xdisplay>=0 && xdisplay<3) display=xdisplay;
 if(xsort>=0 && xsort<4) sort=xsort;
}



void setbatchconfig(int fp)
{
 setvar(fp,&autoremove);
 setvar(fp+1,&autosend);
 setvar(fp+2,&usetypealias);
 setvar(fp+3,&retainbatch);
 if(!retainbatch) deletebatch();
 setvar(fp+4,&batchprompt);
 setvar(fp+5,&completewarning);
 setvar(fp+6,&batoverwrite);
 setvar(fp+7,&batdiscard);
}



void setvtfile(int fp)
{
 setvar(fp,&spconcode);
 setvar(fp+1,&vtinvert);
}



void setvtprint(int fp)
{    
 setvar(fp,&printer);
 setvar(fp+1,&printff);
 setvar(fp+2,&printarea);
}



void setvtdisplay(int fp)
{
 int temp;
 int temp2;

 temp=stack[fp];
 if(temp==0 || temp==1)
 {
  if(vtexists) screenm(temp);
  else        screenmode=temp;
 }

 setvar(fp+1,&insertmode);
 setvar(fp+2,&wrapmode);
 setvar(fp+3,&smooth);

 temp=stack[fp+4];
 if(temp==80 || temp==132)
 {
  if(vtexists) 
  {
   if(temp!=width)
   {
    if(temp==80) go80();
    else         go132();
   }
  }   
  else width=temp;
 }

 setvar(fp+5,&vtcurs);
 setvar(fp+6,&vtblock);
 setvar(fp+7,&destbkspc);

 temp=stack[fp+8];
 if(temp>=0 && temp<4)
 {
  if(vtexists) vtsetstatusline(temp);
  else        
  {
   vtstatus=temp;
   vtheight=vtstatus?25:24;
  }
 }

 temp=stack[fp+9];
 temp2=stack[fp+10];

 if(temp!=vtzoom.mul || temp2!=vtzoom.div)
 {
  if(temp>=0 && temp2>=0)
  {
   vtzoom.var=0;
   vtzoom.mul=temp;
   vtzoom.div=temp2;
   if(vtexists) vtdozoom();
  }
 }

 temp=stack[fp+11];
 if(temp==0 || temp==1)
 {
  if(vtexists && vtzoom.var!=temp)
  {
   vtzoom.var=temp;
   vtvarzoom();
  }
  else vtzoom.var=temp;
 }
}

       

void setvtset(int fp)
{
 int gn=stack[fp];
 int set=stack[fp+1];

 if(set>=0 && set<VTMAXSET)
 {
  if(gn>=0 && gn<4) vtgn[gn]=set;
  else
  if(gn==4) vtncs=set;
  else
  if(gn==5) vtupss=set;
 }
}



void setvtgrl(int fp)
{
 int lr=stack[fp];
 int gn=stack[fp+1];

 if(gn>=0 && gn<4)
 {
  if(lr==0) vtgl=gn;
  else
  if(lr==1) vtgr=gn;
 }
}

        

void setvtkey(int fp)
{
 setvar(fp+0,&newlinemode);
 setvar(fp+1,&automode);
 keyboardoncaret(1);
 setvar(fp+2,&cursorkeymode);
 setvar(fp+3,&keypadmode);
 setvar(fp+4,&vtswopbs);
}



void setvtgeneral(int fp)
{
 int temp;

 strcpy(vtanswerback,stringptr(stack[fp]));
 setvar(fp+1,&vtbeep);

 temp=stack[fp+2];

 if(temp>24)
 {
  if(vtexists) vtuserbuffsize(temp);
  else         vtdefbuffsize=temp;
 }

 setvar(fp+3,&vtlock);
}



void setvtline(int fp)
{
 int temp;

 setvar(fp+0,&localmode);
 setvar(fp+1,&echomode);
 setvar(fp+2,&txcrlnf);
 setvar(fp+3,&rxcrlnf);

 temp=stack[fp+4];
 if(temp>=0 && temp<3) concode=temp;

 setvar(fp+5,&bit8c);
}




void setvttabs(int fp)
{
 char * p=stringptr(stack[fp]);
 int    i=0;

 while(*p) tabs[i++]=(*p++)=='T';

 vtrefreshtabs();
}





void setvxfile(int fp)
{
 setvar(fp+0,&spconcode);
 setvar(fp+1,&vxinvert);
 setvar(fp+2,&vxhearsayff);
}

          

void setvxdisplay(int fp)
{
 int temp;
 int temp2;

 if(setvar(fp+0,&vxkeypad) && vxexists)
 {
  if(vxkeypad) vxkeypadopen();
  else         vxkeypadclose();
 }

 setvar(fp+1,&vxcurs);
 setvar(fp+2,&vxblock);



 temp=stack[fp+3];
 temp2=stack[fp+4];

 if(temp>=0 && temp2>=0)
 {
  if(vxexists)
  {
   if(temp!=vscr->zoom.mul || temp2!=vscr->zoom.div)
   {
    vscr->zoom.var=0;
    vscr->zoom.mul=temp;
    vscr->zoom.div=temp2;
    vxdozoom();
   }
  }
  vxdefz.mul=temp;
  vxdefz.div=temp2;
 }

 temp=stack[fp+5];

 if(temp==0 || temp==1)
 {
  if(vxexists && vscr->zoom.var!=temp)
  {
   vscr->zoom.var=temp;
   vxmainvarzoom();
  }
  vxdefz.var=temp;
 }
}





void setvxkeyboard(int fp)
{
 setvar(fp+0,&vxreturnishash);
 setvar(fp+1,&vxauto);
 keyboardoncaret(1);
}



void setcampuskeyboard(int fp)
{
 setvar(fp+0,&campusreturnishash);
}


void setcampusdefault(int fp)
{
 int term=stack[fp];
 if(term==TERMVX || term==TERMVT100)  campusdefault=term;
}


void setvxgeneral(int fp)
{
 strcpy(vxanswerbackstring,stringptr(stack[fp]));
 setvar(fp+1,&vxbeep);
 strcpy(vxmbxreply,stringptr(stack[fp+2]));
}



void setvxsend(int fp)
{
 int temp;

 strcpy(vxprefix,stringptr(stack[fp+0]));
 strcpy(vxsuffix,stringptr(stack[fp+1]));
 strcpy(vxaseq,stringptr(stack[fp+2]));
 strcpy(vxatseq,stringptr(stack[fp+3]));
 strcpy(vxsolseq,stringptr(stack[fp+4]));
 setvar(fp+5,&vxshortlines);
 setvar(fp+6,&vxechocheck);

 temp=stack[fp+7];
 if(temp>=0 && temp<99) sprintf(vxechopacestring,"%d",temp);

 setvar(fp+8,&vxescseq);
}



void setvxline(int fp)
{
 int temp;

 setvar(fp+0,&vxlocal);
 setvar(fp+1,&vxlocalecho);
 setvar(fp+2,&vxtxcrlnf);
 setvar(fp+3,&vxrxcrlnf);

 temp=stack[fp+4];
 if(temp>=0 && temp<3) concode=temp;

 setvar(fp+5,&vxbit8c);
}



void setvxbuff(int fp)
{
 int temp;

 setvar(fp+0,&vxdeftools);

 temp=stack[fp+1];
 if(temp>0) vxbdefz.mul=temp;
 temp=stack[fp+2];
 if(temp>0) vxbdefz.div=temp;

 setvar(fp+3,&vxbdefz.var);
}







void settekfile(int fp)
{
 setvar(fp+0,&spconcode);
 setvar(fp+1,&tekinvert);
}




void setpset(int fp,int copies,pset * ps)
{
 int temp;

 temp=stack[fp];

 if(temp==1 || temp==0)
 {
  ps->flags&=~PORT;
  if(temp) ps->flags|=PORT;
 }


 temp=stack[fp+1];

 if(temp>0)
 {
  ps->xmul=temp;
  ps->xdiv=100;
 }

 temp=stack[fp+2];

 if(temp>0)
 {
  ps->ymul=temp;
  ps->ydiv=100;
 }

 temp=stack[fp+3];

 if(temp>=0) ps->cx=frommms(temp);

 temp=stack[fp+4];

 if(temp>=0) ps->cy=frommms(temp);

 if(copies)
 {
  temp=stack[fp+5];
  if(temp>0) ps->copies=temp;
 }
}



void settekprint(int fp)
{
 int temp=stack[0+fp]-2;
 int newmargins;

 newmargins=tekmargins;

 if(temp>=0 && temp<=1) tekdumptype=temp;
 setvar(fp+1,&printer);
 setvar(fp+2,&newmargins);
 setpset(fp+3,1,&tekpset);

 if(newmargins!=tekmargins)
 {
  tekprupdate();
  tekmargins=newmargins;
  tekprupdate();
 }
}



void setvxprint(int fp)
{
 int temp=stack[0+fp]-1;
 if(temp>=VXTEXT && temp<=VXGRPOS) vxdump=temp;
 setpset(fp+1,0,&vxpset);
 setvar(fp+6,&vxprintff);
}



void settekgeneral(int fp)
{
 int temp;
 int temp2;

 setvar(fp+0,&tek4010);
 setvar(fp+1,&tektextplane);
 setvar(fp+2,&teklockcols);

 temp=stack[fp+3];
 temp2=stack[fp+4];

 if(temp>0 && temp2>0)
 {
  if(temp!=tekzoom.mul || temp2!=tekzoom.div)
  {
   tekzoom.var=0;
   tekzoom.mul=temp;
   tekzoom.div=temp2;
   if(tekexists) tekdozoom();
  }
 }

 temp=stack[fp+5];

 if(temp==0 || temp==1)
 {
  if(tekexists && tekzoom.var!=temp)
  {
   tekzoom.var=temp;
   tekvarzoomlo();
  }
  else tekzoom.var=temp;
 }
}



void settekindex(int fp)
{
 int index;
 int r;
 int g;
 int b;

 index=stack[fp];
 r=stack[fp+1];
 g=stack[fp+2];
 b=stack[fp+3];

 if(index>=0 && index<16 && r>=0 && r<256
                         && g>=0 && g<256
                         && b>=0 && b<256)
 {
  tekindex[index]=(b<<24)+(g<<16)+(r<<8);

 }
}


void settekline(int fp)
{
 int temp=stack[fp];
 if(temp>=0 && temp<16) teklineindex=temp;
}



void settektext(int fp)
{
 int temp=stack[fp];
 if(temp>=0 && temp<16) tekfontindex=temp;
}


void settekfill(int fp)
{
 int temp=stack[fp];
 if(temp>=0 && temp<16) tekfillindex=temp;
}



void settekback(int fp)
{
 int temp=stack[fp];
 if(temp>=0 && temp<16) tekbackindex=temp;
}




void xsetvasscom(int fp)
{
 int temp;
 int i;

 setvar(fp+0,&srxm);
 setvar(fp+1,&stxm);

 temp=stack[fp+2];

 for(i=0;i<6;i++)
 {
  if((1<<(5+i))==temp)
  {
   smbl=i;
   break;
  }
 }
}


int internal_link(int fp)
{
 return(internallink(stack[fp]));
}



void setspeed(int fp)
{
 settxrate(stack[fp]);
 setrxrate(stack[fp+1]);
}


void setbits(int fp)
{
 setdatabits(stack[fp]);
 setparitybits(stack[fp+1]);
 setstopbits(stack[fp+2]);
}


void setline(int fp)
{
 setflow(stack[fp]);
 setvar(fp+1,&filter);
 setvar(fp+2,&answer);
 setanswer(answer);
}


void setlink(int fp)
{
 driversetlink(stack[fp]);
 setvar(fp+1,&trickle);
}


void setautoredial(int fp)
{
 setvar(fp+0,&redial);
 attempts=stack[fp+1];
 ardelay=stack[fp+2]*100;
}


void setcomms(int fp)
{
 setvar(fp+0,&prefix);
}



void tprints(int fp)
{
 convertstringterm(stringptr(stack[fp]));
}



void tprinti(int fp)
{
 char string[32];
 sprintf(string,"%d",stack[fp]);
 convertstringterm(string);
}

void tputc(int fp)
{
 ttywrite(stack[fp]);
}


int ourgetprompt(int fp)
{
 return(getprompt(stringptr(stack[fp]),stack[fp+1]));
}



/* void sprints(string & s);   // send string to port */

void sprints(int fp)
{
 convertstringline(stringptr(stack[fp]));
}


/* void sprinti(int i);                // print int to port */

void sprinti(int fp)
{
 char string[32];
 sprintf(string,"%d",stack[fp]);
 convertstringline(string);
}



/* void pause(int timeout);            // wait, but keep on polling */

void pause(int fp)
{
 int time=clock()+stack[fp];

 do
 {
  if(scriptstop()) break;
  if(scriptpoll) poll(FORCEZERO);
 } while(time>clock());
}



/* int  sreads(string & s,int timeout,int max); */
/*
// try to read string (max chars) from port
// return 1 if string was terminated with
// CR/LF
*/


int sreads(int fp)
{
 int  timeout=stack[fp+1]+clock();
 char temp[128];
 int  s=stack[fp];
 int  max=stack[fp+2];
 int  first;
 int  code=0;
 int  totlen=1;
 int  index=0;
 int  byte;

 first=1;


 while(clock()<timeout)
 {
  if((byte=getbyte())==-1)
  {
   if(scriptstop()) break;
   if(scriptpoll) pollzt();
  }
  else
  {     /* we got a byte */
   temp[index++]=byte;
   temp[index]=0;
   totlen++;


   if(index==127 || byte==CR || byte==LF || totlen>=max)
   {
    if(first)
    {
     assignstring(s,temp);
     first=0;
    }
    else
     appendstring(s,temp);

    index=0;

    if(byte==CR || byte==LF || totlen>=max) 
    {
     code=1;
     break;
    }
   }
  }
 }

 return(code);
}



/* int  sreadtext(string & s,int timeout,int max); */
/*
// try to read string (max chars) from port
// return 1 if string was terminated with
// CR/LF
// no ctrl codes are passed on, string terminates with 0
*/


int sreadtext(int fp)
{
 int  timeout=stack[fp+1]+clock();
 char temp[128];
 int  s=stack[fp];
 int  max=stack[fp+2];
 int  first;
 int  code=0;
 int  totlen=1;
 int  index=0;
 int  byte;

 first=1;


 while(clock()<timeout)
 {
  if((byte=getbyte())==-1)
  {
   if(scriptstop()) break;
   if(scriptpoll) pollzt();
  }
  else
  {     /* we got a byte */
   if(byte>=SPC)
   {
    temp[index++]=byte;
    temp[index]=0;
    totlen++;
   }

   if(index==127 || totlen>=max || (index && (byte==CR || byte==LF)))
   {
    if(first)
    {
     assignstring(s,temp);
     first=0;
    }
    else
     appendstring(s,temp);

    index=0;

    if(byte==CR || byte==LF || totlen>=max) 
    {
     code=1;
     break;
    }
   }
  }
 }
 return(code);
}



/* int  sgetc(int timeout);            // get byte from port */
/* int  sputc(int c);                  // put byte to port   */


int sgetc(int fp)
{
 int timeout=stack[fp]+clock();
 int code;

 do
 {
  if((code=getbyte())!=-1) break;
  if(scriptstop()) break;
  if(scriptpoll) pollzt();
 }
 while(clock()<timeout);

 return(code);
}


int sputc(int fp)
{
 return(outbyte(stack[fp]));
}


int sonline(int fp)
{
 return(online);
 fp=0;
}



/*****************************************************************************/


static char * termnames[TERMMAX]=
{
 "VIEWDATA",
 "MINITEL",
 "ANSI",
 "VT320",
 "VT102",
 "VT52",
 "TEK4105",
 "TELETYPE",
 "CAMPUS"
};


static char * cnames[20]=
{
 "USASCII","BRITISH","DUTCH","FINNISH","FRENCH","FRENCHCAN","GERMAN",
 "ITALIAN","NORWEGIAN","PORTUGUESE","SPANISH","SWEDISH","SWISS",
 "LATIN1","SPECGRAPH","SUPPGRAPH","TECHNICAL","ALTROM",
 "ALTGRAPH","DRCS"
};


static char * linemode[3]=
{
 "ACT","IGNORE","DISPLAY"
};


static char * protocol[PNONE]=
{
 "XMODEM","XMODEM1K","YMODEM","ZMODEM","KERMIT","SEALINK","ASCII","CET"
};

static char * xmodes[3]=
{
 "CHECK","CRC","GMODE"
};


static char * bsize[3]=
{
 "LARGE", "SMALL", "INFO"
};


static char * bsort[4]=
{
 "NAME", "TYPE", "SIZE", "DATE"
};


static char * vtsts[4]=
{
 "NONE","LOCAL","HOST","TABS"
};


static char * aeol[5]=
{
 "CR","LF","CRLF","LFCR","RAW"
};


static char * flowname[3]=
{
 "NONE","RTSCTS","XONXOFF"
};

static char * lname[3]=
{
 "NONE","VASSCOM","MNP"
};

static char * prnames[4]=
{
 "TEXTPRINT","EPSON","IBM","DRIVER"
};


static char * vxdumpnames[3]=
{
 "TEXTDUMP","GRNEG","GRPOS"
};




void hsystdheader(FILE * fp,char * name)
{
 char string[64];
 rfprintf(fp,"//->%s\n",name);
 writesystimedate(string);
 rfprintf(fp,"// Produced by Hearsay at %s\n//\n//\n\n\n",string);
}




char *  sqone(char * string,int byte)
{
 *string++=',';
 *string++='\"';
 string=uncode(string,byte);
 *string++='\"';
 return(string);
}



void ktxp(FILE * fp)
{
 char buff[128];
 char * string=buff;

 sprintf(string,"setkermitparam(TX,%d,%d",spsiz,npad);
 string+=strlen(string);

 string=sqone(string,padch);
 string=sqone(string,mystch);
 string=sqone(string,seol);

 sprintf(string,",%d",timint);
 string+=strlen(string);

 string=sqone(string,myctlq);
 strcpy(string,");\n");

 rfprintf(fp,buff);
}



void krxp(FILE * fp)
{
 char buff[128];
 char * string=buff;

 sprintf(string,"setkermitparam(RX,%d,%d",urpsiz,mypadn);
 string+=strlen(string);

 string=sqone(string,mypadc);
 string=sqone(string,stchr);
 string=sqone(string,eol);

 sprintf(string,",%d",rtimo);
 string+=strlen(string);

 string=sqone(string,ctlq);
 strcpy(string,");\n");

 rfprintf(fp,buff);
}




void atxp(FILE * fp)
{
 char buff[128];
 char scrap[128];
 char * string=buff;
 char * temp;

 sprintf(string,"setasciitx");
 temp=string+=strlen(string);

 string=sqone(string,txprompt);
 *temp='(';

 sprintf(string,",%s",unquotec(aeol[txeol],scrap));
 string+=strlen(string);

 string=sqone(string,txbegin);
 string=sqone(string,txend);
 string=sqone(string,txstart);
 string=sqone(string,txstop);

 sprintf(string,",%d",txcharpace);
 string+=strlen(string);

 sprintf(string,",%d",txlinepace/10);
 string+=strlen(string);

 sprintf(string,",%cEXPAND,%cLOCAL);\n",33-txexpand,33-asctxe);

 rfprintf(fp,buff);
}




void arxp(FILE * fp)
{
 char buff[128];
 char scrap[128];
 char * string=buff;
 char * temp;

 sprintf(string,"setasciirx");
 temp=string+=strlen(string);

 string=sqone(string,rxprompt);
 *temp='(';

 sprintf(string,",%s",unquotec(aeol[rxeol],scrap));
 string+=strlen(string);

 string=sqone(string,rxtprompt);

 sprintf(string,",%d",rxpace/10);
 string+=strlen(string);

 string=sqone(string,rxbegin);
 string=sqone(string,rxend);

 sprintf(string,",%cLOCAL);\n",33-ascrxe);

 rfprintf(fp,buff);
}



void svttabs(FILE * fp)
{
 char buff[256];
 char * string=buff;
 int    i;

 sprintf(string,"setvttabs(\"");
 string+=strlen(string);
 for(i=0;i<TTYCOLS;i++) string[i]=tabs[i]?'T':'.';
 string+=TTYCOLS;
 sprintf(string,"\");\n");

 rfprintf(fp,buff);
}


static void saveps(FILE * fp,pset * ps)
{
 char cx[32];
 char cy[32];

 gsprint(cx,ps->cx,0);
 gsprint(cy,ps->cy,0);

 rfprintf(fp,"%cPORTRAIT,%d,%d,%s,%s",33-((ps->flags & PORT)!=0),(ps->xmul*100)/ps->xdiv,(ps->ymul*100)/ps->ydiv,cx,cy);
}



/* save current configuration with given filename */

int saveconfig(char * filename)
{
 FILE * fp;
 int    i;
 char   temp[32];
 char   scrap[256];
 int    code;

 fp=ropen(filename,"wb");
 if(!fp) return(0);

  hsystdheader(fp,leaf(filename));

  rfprintf(fp,"void main(void)\n{\n");

  rfprintf(fp,"setspeed(%d,%d);\n",txbitrate,rxbitrate);
  rfprintf(fp,"setbits(%d,%c,%d);\n",databits,"NEOMS"[paritybits],stopbits);

  rfprintf(fp,"setline(%s,%cFILTER,%cANSWER);\n",
                                    flowname[flow],33-filter,33-answer);

  rfprintf(fp,"setlink(%s,%cTRICKLE);\n",lname[linktype],33-trickle);

  rfprintf(fp,"setvasscom(%cTXBLOCK,%cRXBLOCK,%d);\n",33-srxm,33-stxm,1<<(5+smbl));

  rfprintf(fp,"setftp(%s);\n",protocol[ftprotocol]);
  rfprintf(fp,"setxmodem(%s);\n",xmodes[xmode-1]);
  rfprintf(fp,"setymodem(%s,%d);\n",xmodes[ymode-1],ysize?1024:128);
  rfprintf(fp,"setzmodem(%cCRC32,%cAUTORESUME,%cAUTODLOAD);\n",
                 33-Wantfcs32,33-AutoResume,33-zmautodload);
  rfprintf(fp,"setcet(%cSLOW,%cCET,\"%s\",%cAUTORESUME);\n",
   33-vxslotel,33-vxcetel,unquotec(vxceteol,scrap),
   33-vxautoresume);


  uncode(temp,ebq);
  rfprintf(fp,"setkermit(%cBINARY,%cWINDOWS,%cQUOTE8,\"%s\",CHECK%d);\n",
    33-binary,33-swcapr,33-ebqflg,unquotec(temp,scrap),bctr);

  ktxp(fp);
  krxp(fp);
  atxp(fp);
  arxp(fp);


  rfprintf(fp,"setbatch(%s,%s);\n",bsize[display],bsort[sort]);

  rfprintf(fp,"setbatchconfig(%cREMOVE,%cSEND,%cALIAS,%cRETAIN,%cPROMPT,%cWARN,%cOVERWRITE,%cDISCARD);\n",33-autoremove,33-autosend,33-usetypealias,33-retainbatch,33-batchprompt,33-completewarning,33-batoverwrite,33-batdiscard);


  rfprintf(fp,"setvtfile(%cCTRLCODES,%cCOMPLEMENT);\n",33-spconcode,33-vtinvert);

  rfprintf(fp,"setvtprint(%cREMOTE,%cFF,%cFULL);\n",33-printer,33-printff,33-printarea);


  rfprintf(fp,"setvtdisplay(%cREVERSE,%cINSERT,%cWRAP,%cSMOOTH,%d,%cCURSOR,%cBLOCK,%cDESTBKSPC,%s,%d,%d,%cVARIABLE);\n",33-screenmode,33-insertmode,33-wrapmode,33-smooth,width,33-vtcurs,33-vtblock,33-destbkspc,vtsts[vtstatus],vtzoom.mul,vtzoom.div,33-vtzoom.var);


  for(i=0;i<4;i++) rfprintf(fp,"setvtset(G%d,%s);\n",i,cnames[vtgn[i]]);

  rfprintf(fp,"setvtset(NRCS,%s);\n",cnames[vtncs]);
  rfprintf(fp,"setvtset(UPSS,%s);\n",cnames[vtupss]);
  rfprintf(fp,"setvtgrl(GL,G%d);\n",vtgl);
  rfprintf(fp,"setvtgrl(GR,G%d);\n",vtgr);


  rfprintf(fp,"setvtkey(%cNEWLINE,%cREPEAT,%cCURSOR,%cKEYPAD,%cDELBKSPC);\n",33-newlinemode,33-automode,33-cursorkeymode,33-keypadmode,33-vtswopbs);


  rfprintf(fp,"setvtgeneral(\"%s\",%cBELL,%d,%cLOCK);\n",unquotec(vtanswerback,scrap),33-vtbeep,vtdefbuffsize,33-vtlock);


  rfprintf(fp,"setvtline(%cLOCAL,%cECHO,%cTXCRLF,%cRXCRLF,%s,%cBIT8);\n",33-localmode,33-echomode,33-txcrlnf,33-rxcrlnf,linemode[concode],33-bit8c);

  svttabs(fp);

  rfprintf(fp,"setvxfile(%cCTRLCODES,%cCOMPLEMENT,%cCEPT3);\n",33-spconcode,33-vxinvert,33-vxhearsayff);


  rfprintf(fp,"setvxdisplay(%cKEYPAD,%cCURSOR,%cBLOCK,%d,%d,%cVARIABLE);\n",
   33-vxkeypad,33-vxcurs,33-vxblock,vxexists?vscr->zoom.mul:vxdefz.mul,
   vxexists?vscr->zoom.div:vxdefz.div,33-(vxexists?vscr->zoom.var:vxdefz.var));


  rfprintf(fp,"setvxprint(%s,",vxdumpnames[vxdump]);
  saveps(fp,&vxpset);
  rfprintf(fp,",%cFF);\n",33-vxprintff);


  rfprintf(fp,"setvxkeyboard(%cRETURN,%cREPEAT);\n",
                         33-vxreturnishash,33-vxauto);

  rfprintf(fp,"setcampuskeyboard(%cRETURN);\n",33-campusreturnishash);


  rfprintf(fp,"setvxgeneral(\"%s\",%cBELL,\"%s\");\n",
               unquotec(vxanswerbackstring,scrap),
               33-vxbeep,
               unquotec(vxmbxreply,scrap+128));


  setechopace();
  rfprintf(fp,"setvxsend(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",%cSHORT,%cECHO,%d,%cESCSEQ);\n",
            unquotec(vxprefix,scrap),
            unquotec(vxsuffix,scrap+32),
            unquotec(vxaseq,scrap+64),
            unquotec(vxatseq,scrap+96),
            unquotec(vxsolseq,scrap+128),
            33-vxshortlines,
            33-vxechocheck,vxechopace,33-vxescseq);


  rfprintf(fp,"setvxline(%cLOCAL,%cECHO,%cTXCRLF,%cRXCRLF,%s,%cBIT8);\n",  33-vxlocal,33-vxlocalecho,33-vxtxcrlnf,33-vxrxcrlnf,linemode[concode],33-vxbit8c);


  vxbsetdeflt();
  rfprintf(fp,"setvxbuff(%cTOOLS,%d,%d,%cVARIABLE);\n",33-vxdeftools,vxbdefz.mul,vxbdefz.div,33-vxbdefz.var);


  rfprintf(fp,"settekfile(%cCTRLCODES,%cCOMPLEMENT);\n",33-spconcode,33-tekinvert);


  rfprintf(fp,"settekprint(%s,%cREMOTE,%cMARGINS,",vxdumpnames[tekdumptype+1],33-printer,33-tekmargins);

  saveps(fp,&tekpset);

  rfprintf(fp,",%d);\n",tekpset.copies);


  rfprintf(fp,"settekgeneral(%cTEK4010,%cTEXT,%cLOCK,%d,%d,%cVARIABLE);\n",
          33-tek4010,33-tektextplane,33-teklockcols,tekzoom.mul,tekzoom.div,
          33-tekzoom.var);


  for(i=0;i<16;i++)
    rfprintf(fp,"settekindex(%d,%d,%d,%d);\n",i,((tekindex[i])>>8)&0xFF,((tekindex[i])>>16)&0xFF,((tekindex[i])>>24)&0xFF);

  rfprintf(fp,"settekline(%d);\n",teklineindex);
  rfprintf(fp,"settektext(%d);\n",tekfontindex);
  rfprintf(fp,"settekfill(%d);\n",tekfillindex);
  rfprintf(fp,"settekback(%d);\n",tekbackindex);


  rfprintf(fp,"setautoredial(%cREDIAL,%d,%d);\n",33-redial,attempts,ardelay/100);
  rfprintf(fp,"setcomms(%cPREFIX);\n",33-prefix);


  rfprintf(fp,"}\n\n");

  code=rerror(fp);

  rclose(fp);
  savetypeclose(fp,filename);

 return(!code);
}


/* save current config as default */

void savedefaultconfig(void)
{
 char string[256];

 saveftype=SCRIPT;

 sprintf(string,"%s.!Config",path(AUTOP));
 saveconfig(string);
}



void savechoices(void)
{
 FILE * fp;
 char   name[256];

 sprintf(name,"%s.!Choices",path(AUTOP));

 fp=fopen(name,"wb");

 if(fp)
 {
  hsystdheader(fp,"!Choices");

  rfprintf(fp,"void main(void)\n{\n");
  rfprintf(fp,"setdefterminal(%s);\n",termnames[defaultterminal]);
  rfprintf(fp,"setchoices(%cNEWDATA,%cCONFIRM,%cLOGFILE,%s,%cTONE);\n",33-newdata,33-doconfirm,33-logfile,prnames[prtype],33-tonedial);

  if(modemdriverloaded) rfprintf(fp,"specifydriver(\"%s\");\n",drivername);

  rfprintf(fp,"setprinter(%d,%d,%s);\n",prlinespp,prwidth,aeol[preol]);

  rfprintf(fp,"}\n\n");

  fclose(fp);
  setftype(name,SCRIPT);
 }
}



static void addfiles(char * name,int remove)
{
 fxstat f;
 char   temp[256];
 int    code;

 startscan();
 while(1)
 {
  strcpy(temp,name);

  if(!nextitem(temp,&f,NULL)) break;

  if(f.f.object==1)
  {
   strcat(temp,".");
   strcat(temp,f.name);

   code=xaddfile(temp,0,1);
   if(remove && code) xremfile();

   changedriver(1);
  }
 }
}


/* return 1==OK 0==ERROR */

int runscript(char * filename,int exec)
{
 int code;
 code=xaddfile(filename,0,0);
 if(code && exec)
 {
  code=xexec("main",NULL,NULL,NULL);
  xremfile();
  changedriver(1);
 }
 return(code);
}


void runscriptpost(void)
{
 xexec("main",NULL,NULL,NULL);
 xremfile();
 changedriver(1);
}


int xexecstuff(char * stuff)
{
 int code;
 code=xaddfile(stuff,1,1);
 if(code) xremfile();
 changedriver(1);
 return(code);
}



void scriptstart(void)
{
 int time;

 xstart();                  /* start up x language    */

 time=clock();

 addfiles(path(LIBP),0);     /* do library */

 xexec("device_initiate",NULL,NULL,NULL);

 addfiles(path(AUTOP),1);     /* auto run */                      


/* activate(); */

/* dprintf(5,"time=%d codesize=%d",clock()-time,xcodesize);
 dprintf(6,"xheapsize=%d xnsyms=%d",xheapsize,xnsyms);  */
}



/*****************************************************************************/


static int  tempdefaultterminal;
static int  temptonedial;
static int  tempnewdata;
static int  tempdoconfirm;
static int  templogfile;
static int  tempprtype;
static char tempdrivername[12];
static int  temppreol;

/* static char * preolnames[5]={"CR","LF","CRLF","LFCR","Raw"}; */

static char * preolnames[5]={"PN4","PN5","PN6","PN7","PN8"};


/* we assume that myrambuff contains menu */

void setpopdriver(void)
{
 int * menu=(int*)myrambuff;
 int   item;

 item=0;

 while(modemdriverloaded)
 {
  tickst(menu,item,!strcmp(menuaddr(menu,item),tempdrivername));
  if(islastm(menu,item)) break;
  item++;
 }
}


static os_error * decodedriver(int m2)
{
 if(m2>=0)
 {
  strcpy(tempdrivername,menuaddr((int*)myrambuff,m2));
  writeicon(whandle[TCHOICES],4,tempdrivername);
  setpopdriver();
 }
 return(NULL);
}


/* static char * printername[4]={"Text","Epson","IBM","Driver"}; */

static char * printername[4]={"PN0","PN1","PN2","PN3"};


static void setpopdefterm(void)
{
 int i;
 for(i=0;i<=TERMMAX;i++)  tickst(term_menu,i,i==tempdefaultterminal);
}

void decodedefterm(int m1)
{
 tempdefaultterminal=m1;
 setpopdefterm();
 writeicon(whandle[TCHOICES],1,termnames[tempdefaultterminal]);
}

static void setpopprinter(void)
{
 int i;
 for(i=0;i<4;i++) tickst(printer_menu,i,i==((tempprtype+1)%4));
}

void decodeprinter(int m1)
{
 if(m1>=0 && m1<4) tempprtype=((3+m1)%4);
 setpopprinter();
 writeicon(whandle[TCHOICES],7,transtoken(printername[tempprtype]));
}



void choicesicon(void)
{
 int handle=whandle[TCHOICES];

 switch(icon)
 {
  case  2:
          setpopdefterm();
          popmenu(term_menu);
          break;

   case 5:
          setupdrivermenu();
          setpopdriver();
          setrammenu(decodedriver);
          popmenu((int*)myrambuff);
          break;

  case  8:
          setpopprinter();
          popmenu(printer_menu);
          break;


  case 19: /* Save   */
  case 16: /* OK     */
          if(strcmp(drivername,tempdrivername))
          {
           strcpy(pendname,tempdrivername);
           pendingdriver=1;
           changedriver(active);
          }
          if(tonedial!=temptonedial) tonedial=drivertonedial(temptonedial);

          defaultterminal=tempdefaultterminal;
          newdata=tempnewdata;
          doconfirm=tempdoconfirm;
          logfile=templogfile;
          printsettype(tempprtype);
          preol=temppreol;

          if(icon==19) savechoices();

  case 17: /* Cancel */
          closedownt(TCHOICES);
          break;

  case 13:
          selectst(handle,13,tempnewdata^=1);
          break;

  case 14:
          selectst(handle,14,tempdoconfirm^=1);
          break;

  case 15:
          selectst(handle,15,templogfile^=1);
          break;

  case 18:
          selectst(handle,18,temptonedial^=1);
          break;

  case 10:
  case 12:
         if(buttons==0x1) icon=(10+12)-icon;

         if(icon==10 && temppreol)   temppreol--;
         else
         if(icon==12 && temppreol<4) temppreol++;
         else                        return;

         writeicon(handle,11,transtoken(preolnames[temppreol]));
         break;
 }
}




void openchoices(void)
{
 int handle;

 if(whandle[TCHOICES])
 {
  forward(whandle[TCHOICES]);
 }
 else
 {
  handle=createwindow(TCHOICES);
  if(!handle) return;

  tempdefaultterminal=defaultterminal;
  temptonedial=tonedial;
  tempnewdata=newdata;
  tempdoconfirm=doconfirm;
  templogfile=logfile;
  tempprtype=prtype;
  temppreol=preol;

  writeicon(handle,1,termnames[tempdefaultterminal]);
  strcpy(tempdrivername,drivername);
  writeicon(handle,4,tempdrivername);
  writeicon(handle,7,transtoken(printername[tempprtype]));
  writeicon(handle,11,transtoken(preolnames[temppreol]));

  selectst(handle,13,tempnewdata);
  selectst(handle,14,tempdoconfirm);
  selectst(handle,15,templogfile);
  selectst(handle,18,temptonedial);

  popup(handle,0);
 }
}


/****************************************************************************/

void setmenusense(int fp)
{
 setvar(fp+0,&menusense);
}


